from abc import ABC, abstractmethod
from pyexpat.errors import messages

import gevent


class BaseDevice(ABC):
    def __init__(self, name, imei, ip, port, protocol_type):
        self._name = name
        self._imei = imei
        self._ip = ip
        self._port = port
        # todo 根据协议类型初始化不同的协议
        self._protocol_type = protocol_type
        self.messages = []

    @property
    def name(self):
        return self._name

    @name.setter
    def name(self, value):
        self._name = value

    @property
    def imei(self):
        return self._imei

    @imei.setter
    def imei(self, value):
        raise AttributeError("You can't change the imei")

    @property
    def ip(self):
        return self._ip

    @ip.setter
    def ip(self, value):
        self._ip = value

    @property
    def port(self):
        return self._port

    @port.setter
    def port(self, value):
        self._port = value

    @property
    def protocol_type(self):
        return self._protocol_type

    @protocol_type.setter
    def protocol_type(self, value):
        self._protocol_type = value

    def _build_message(self,message, args_list, *args, **kwargs):
        """
        构建消息
        :param kwargs:
        :return:
        """
        message = ...  # 根据设备使用protocol来实现message的构建
        return message

    def send_message(self, message, args):
        message = self._build_message(message, args)
        self.messages.append({
            "message": message,
            "type": "send"
        })


    def receive_message(self):
        # 接收消息方法
        message = ...
        self.messages.append({
            "message": message,
            "type": "receive"
        })

    @abstractmethod
    def _build_message(self, *args, **kwargs):
        """
        构建消息
        :param kwargs:
        :return:
        """
        pass

    @abstractmethod
    def active(self):
        """
        激活设备
            当设备激活时，单独起一个协程，用于接收设备消息
        """
        gevent.spawn(self.receive_message)


    @abstractmethod
    def deactive(self):
        pass
